package org.nvframe.component.physics.util;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.Graphics;
import org.nvframe.camera.Camera;
import org.nvframe.event.EventService;
import org.nvframe.event.eventtype.RenderEvent;
import org.nvframe.event.eventtype.RenderListener;
import org.nvframe.manager.ConfigManager;

/**
 * 
 * @author Nik Van Looy
 */
public class PhysicsDebugDraw implements RenderListener {
	
	private World world;
	
	public PhysicsDebugDraw(World world) {
		this.world = world;
		
		EventService.getInstance().addEventListener(this);
	}
	
	/**
	 * 
	 * @param g
	 */
	protected void drawBodies(Graphics g) {
		Body body = world.getBodyList();
		
		while(body != null) {
			drawBody(g, body);
			body = body.getNext();
		} 
	}
	
	/**
	 * 
	 * @param g
	 * @param body
	 */
	protected void drawBody(Graphics g, Body body) {
		Shape shape = body.getShapeList();
		
		while(shape != null) {
			drawShape(g, shape, body);
			shape = shape.getNext();
		} 
	}

	/**
	 * 
	 * @param g
	 * @param shape
	 * @param body
	 */
	private void drawShape(Graphics g, Shape shape, Body body) {
		Camera camera = Camera.getInstance();
		
		switch(shape.getType()) {
			case CIRCLE_SHAPE:
				CircleShape circle = (CircleShape) shape;
            
	            org.newdawn.slick.geom.Circle slickCircle = new org.newdawn.slick.geom.Circle(
	            		body.getPosition().x + circle.getLocalPosition().x - camera.getX(),
	            		body.getPosition().y + circle.getLocalPosition().y - camera.getY(),
	            		circle.getRadius());
	            
	            g.draw(slickCircle);
	            
				break;
				
			case POLYGON_SHAPE:
				PolygonShape poly = (PolygonShape) shape;

				org.newdawn.slick.geom.Polygon slickPoly = new org.newdawn.slick.geom.Polygon();
				
				for(Vec2 vert : poly.getVertices())
					slickPoly.addPoint(body.getPosition().x + vert.x - camera.getX(), 
							body.getPosition().y +vert.y - camera.getY());
				
				g.draw(slickPoly);
				
				break;
				
			default:
				break;
		}
	}

	@Override
	public void onRender(RenderEvent event) {
		if(ConfigManager.getInstance().getActive("engine_physics_drawbodies"))
			drawBodies(event.getGr());
	}
}
